<!-- 视频组件: <me-video src="视频地址" poster="封面图"></me-video>
video标签在APP端是原生组件, 真机APP端下拉时会渲染不及时, 出现悬浮错位现象;
me-video组件, 未播放时自动展示image封面, 播放时才显示video, 提高性能; 如果播放中执行下拉,会自动显示封面, 避免视频下拉悬浮错位;
-->
<template>
	<view class="me-video" :style="{ width: width, height: height }">
		<!-- 播放的时候才渲染video标签 -->
		<!-- #ifndef APP-PLUS -->
		<video
			v-if="showVideo"
			ref="videoRef"
			:id="videoId"
			class="video"
			:class="{ 'full-play': fullplay && !autoplay, 'mescroll-dowload': mescrollDownLoad }"
			:src="src"
			autoplay
			:loop="loop"
			@click="videoClick"
			x5-playsinline="true"
			x5-video-player-type="h5"
			playsinline="true"
			webkit-playsinline="true"
			x5-video-player-fullscreen="false"
			@play="onPlayer"
		></video>
		<!-- #endif -->
		<!-- 播放按钮 -->
		<view v-if="!showVideo || mescrollDownLoad" class="btn-play">
			<view class="triangle"></view>
		</view>
		<!-- 封面 -->
		<image
			v-if="!showVideo || mescrollDownLoad"
			class="poster"
			:src="qiniu(poster)"
			@click="play()"
			mode="aspectFit"
		></image>
	</view>
</template>

<script>
import $mUtils from '@/common/utils'
import store from '@/store'

export default {
	props: {
		// 视频地址
		src: {
			type: String,
			default: ''
		},
		// 封面图
		poster: {
			type: String,
			default: ''
		},
		// 是否自动播放
		autoplay: {
			type: Boolean,
			default: false
		},
		// 是否全屏播放，默认不全屏
		fullplay: {
			type: Boolean,
			default: false
		},
		// 是否循环播放，循环播放可避免Android微信播放完毕显示广告
		loop: {
			type: Boolean,
			default: true
		},
		// 宽度 (需带单位,支持格式: '100%', '300px', '300rpx')
		width: {
			type: String,
			default: '100%'
		},
		// 高度 (需带单位,支持格式: '100%', '300px', '300rpx')
		height: {
			type: String,
			default: '444rpx'
		}
	},
	data() {
		return {
			showCover: false, // 显示封面
			showVideo: this.autoplay, // 是否播放视频
			route: getCurrentPages()[0].route // 所属页面
		}
	},
	computed: {
		// 是否下拉中 或 滚动中 (下拉隐藏视频,显示封面, 仅APP端生效)
		mescrollDownLoad() {
			return this.showCover
		},
		// 视频唯一ID
		videoId() {
			return `video-${Math.random() * 1000}`
		},
		// 获取视频
		getVideo() {
			return store.state.video
		}
	},
	watch: {
		autoplay(val) {
			if (val) this.play()
		},
		getVideo(video) {
			// 当前播放视频以外的暂停并显示封面（保持播放视频唯一）
			if (video.id != this.videoId) {
				this.videoContext.pause()
				this.showCover = true
			} else {
				this.showCover = false
			}
		}
	},
	mounted() {
		// 获取视频组件
		this.videoContext = uni.createVideoContext(this.videoId, this)
		// 获取滚动区域
		this.videoScroll = uni.getStorageSync('videoScroll')

		// 页面显示继续播放
		uni.$on('onShow', () => {
			// 继续播放最后正在播放的视频
			if (getCurrentPages()[0].route == this.getVideo.route && this.getVideo.id == this.videoId) {
				this.videoContext.play()
			}
		})
		// 页面隐藏暂停播放
		uni.$on('onHide', () => {
			// 暂停播放最后正在播放的视频
			if (this.getVideo.id == this.videoId) {
				this.videoContext.pause()
			}
		})
		// 监听Mescroll滚动事件
		uni.$on('onScroll', scrollTop => {
			// 只需要计算当前页面的视频节点
			if (getCurrentPages()[0].route != this.route) return

			// 滚动过程中不断更新节点信息
			const query = uni.createSelectorQuery().in(this)
			query
				.select('.me-video')
				.boundingClientRect(data => {
					// 获取节点距顶部距离位置
					this.videoTop = data.top + scrollTop
					// 只需要判断当前播放的视频是否在可视区
					if (this.getVideo.id == this.videoId) {
						this.getVideoRect()
					}
				})
				.exec()
		})
	},
	methods: {
		//
		/**
		 * @name 判断视频当前位置
		 * @param { reset => 视频进入可视区一半播放自动滚上去 }
		 */
		getVideoRect(reset = false) {
			const query = uni.createSelectorQuery().in(this)
			query
				.select('.me-video')
				.boundingClientRect(data => {
					// 因滚动区域为Mescroll，所以需要减滚动区域外高度
					if (data.top - this.videoScroll.otherH < 0) {
						if (reset) {
							// 视频进入可视区一半播放自动滚上去
							uni.$emit('scrollTo', this.videoTop - this.videoScroll.otherH)
						} else {
							// 向上滚动时判断是否离开可视区
							this.showCover = true
						}
					} else if (data.top - this.videoScroll.otherH > this.videoScroll.scrollH - data.height) {
						if (reset) {
							// 视频进入可视区一半播放自动滚上去
							uni.$emit('scrollTo', this.videoTop - this.videoScroll.otherH)
						} else {
							// 向下滚动时判断是否离开可视区
							this.showCover = true
						}
					}
				})
				.exec()
		},
		// 播放
		play() {
			/* #ifndef APP-PLUS */
			this.showVideo = true
			this.showCover = false
			this.videoContext.play()
			this.wxAutoPlay()
			// 只需要判断当前播放的视频是否在可视区
			if (this.getVideo.id == this.videoId) {
				this.getVideoRect(true)
			}
			/* #endif */

			/* #ifdef APP-PLUS */
			$mUtils.push({
				path: '/pages/shopping/playVideo',
				query: {
					src: this.src
				}
			})
			/* #endif */
		},
		// 视频点击事件
		videoClick() {
			// 全屏播放时，点击视频退出
			if (this.fullplay) this.showVideo = false
		},
		// 监听视频播放
		onPlayer() {
			store.state.updateVideo({
				id: this.videoId,
				route: getCurrentPages()[0].route
			})
			// 只需要判断当前播放的视频是否在可视区
			if (this.getVideo && this.getVideo.id == this.videoId) {
				this.getVideoRect(true)
			}
		},
		// 解决微信端视频无法自动播放的问题
		wxAutoPlay() {
			// #ifdef H5
			// 微信端
			if (navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger') {
				// iOS
				let head = document.getElementsByTagName('head')[0]
				let wxscript = document.createElement('script')
				wxscript.type = 'text/javascript'
				wxscript.src = 'https://res.wx.qq.com/open/js/jweixin-1.6.0.js'
				head.appendChild(wxscript)
				let doPlay = () => {
					this.$refs.videoRef.play()
				}
				wxscript.onload = function () {
					window.wx.config({
						debug: !1,
						appId: '',
						timestamp: 1,
						nonceStr: '',
						signature: '',
						jsApiList: []
					})
					window.wx.ready(doPlay)
				}
				// Android
				document.addEventListener('WeixinJSBridgeReady', doPlay, false)
				// 先尝试播放
				setTimeout(() => {
					doPlay()
				}, 20)
			}
			// #endif
		}
	}
}
</script>

<style lang="scss">
.me-video {
	position: relative;
	background-color: #000;
	overflow: hidden;
	// 播放按钮
	.btn-play {
		z-index: 9;
		position: absolute;
		left: 50%;
		top: 50%;
		transform: translate(-50%, -50%);
		width: 100rpx;
		height: 100rpx;
		border-radius: 50%;
		background-color: rgba(0, 0, 0, 0.75);
		pointer-events: none;
		.triangle {
			position: absolute;
			left: 50%;
			top: 50%;
			transform: translate(-25%, -50%);
			width: 0;
			height: 0;
			border-top: 16rpx solid transparent;
			border-left: 24rpx solid #fff;
			border-bottom: 16rpx solid transparent;
		}
	}
	// 封面图
	.poster {
		width: 100%;
		height: 100%;
		vertical-align: bottom;
	}
	// 视频 (默认非全屏播放)
	.video {
		z-index: 8;
		position: absolute;
		top: 0;
		left: 0;
		width: 100%;
		height: 100%;
		// 全屏播放
		&.full-play {
			z-index: 999;
			position: fixed;
		}
		// 下拉时隐藏视频
		&.mescroll-dowload {
			display: none;
		}
	}
}
</style>
